﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DBS_semka_2
{
    class cBlock
    {
        const int HEADER_LENGTH = 17;

        private int piNumberOfRecords;

        private int piKeyLength;

        private int piRecordLength;

        private int piHeaderLength = 8 + 1 + 2 * 4; 

        private int piNumberOfRecordsInBucket;

        private long piAddress;

        public long iAddress
        {
            get { return piAddress; }
            set { piAddress = value; }
        }

        public int iNumberOfRecords
        {
            get { return piNumberOfRecords; }
            set { piNumberOfRecords = value; }
        }
        private int piDepth;

        public int iDepth
        {
            get { return piDepth; }
            set { piDepth = value; }
        }
        private bool pbUsed;

        public bool bUsed
        {
            get { return pbUsed; }
            set { pbUsed = value; }
        }
        private long piChain;

        public long iChain
        {
            get { return piChain; }
            set { piChain = value; }
        }

        public cRecord this[int index]
        {
            get
            {
                return paValues[index];
            }
            set
            {
                paValues[index] = value;
            }
        }

        List<cRecord> paValues;

        public cBlock(int pa_iKeyLength,int pa_iRecordsPerBlock, long pa_iAddress)
        {
            piKeyLength = pa_iKeyLength;
            piNumberOfRecordsInBucket = pa_iRecordsPerBlock;
            piNumberOfRecords = 0;
            pbUsed = true;
            piRecordLength = piKeyLength + 2 * 8;
            piDepth = 1;
            piChain = -1;
            piAddress = pa_iAddress;
        }

        public cBlock(int pa_iKeyLength, int pa_iRecordsPerBlock, long pa_iAddress, byte[] pa_iInput)
        {
            piKeyLength = pa_iKeyLength;
            piNumberOfRecordsInBucket = pa_iRecordsPerBlock;
            piRecordLength = piKeyLength + 2 * 8;
            piAddress = pa_iAddress;
            pbUsed = true;
            byte[] aBuffer = null;
            
            // Vytvorenie hlavicky
            Array.Copy(pa_iInput, 0, aBuffer, 0, 4);
            piDepth = BitConverter.ToInt32(aBuffer,0);
            aBuffer = null;
            Array.Copy(pa_iInput, 4, aBuffer, 0, 4);
            piNumberOfRecords = BitConverter.ToInt32(aBuffer, 0);
            aBuffer = null;
            Array.Copy(pa_iInput, 8, aBuffer, 0, 8);
            piChain = BitConverter.ToInt64(aBuffer, 0);
            aBuffer = null;
            Array.Copy(pa_iInput, 16, aBuffer, 0, 1);
            pbUsed = BitConverter.ToBoolean(aBuffer, 0);

            // Vytvorenie zaznamov
            int iBegin = 17;
            for (int ii = 0; ii < piNumberOfRecordsInBucket; ii++)
            {
                aBuffer = null;
                Array.Copy(pa_iInput, iBegin, aBuffer, 0, piRecordLength);
                cRecord oTempBlock = new cRecord(piKeyLength, aBuffer);
                paValues.Insert(ii, oTempBlock);
                iBegin += piRecordLength;
            }
        }

        public byte[] toByteArray()
        {
            byte[] aReturn = new byte[HEADER_LENGTH + piRecordLength * piNumberOfRecordsInBucket];
            Array.Copy(System.BitConverter.GetBytes(piDepth), 0, aReturn, 0, 4);
            Array.Copy(System.BitConverter.GetBytes(piNumberOfRecords), 0, aReturn, 4, 4);
            Array.Copy(System.BitConverter.GetBytes(piChain), 0, aReturn, 8, 8);
            Array.Copy(System.BitConverter.GetBytes(pbUsed), 0, aReturn, 16, 1);
            int iLength = 17;
            for (int ii = 0; ii < piNumberOfRecords; ii++)
            {
                Array.Copy(paValues[ii].toByteArray(), 0, aReturn, iLength, piRecordLength);
                iLength += piRecordLength;
            }
            return aReturn;
        }

        public bool addRecord(byte[] pa_aKey, long pa_iRowid, long pa_iAddress)
        {
            if (iNumberOfRecords < piNumberOfRecordsInBucket)
            {
                paValues.Add(new cRecord(pa_aKey, pa_iRowid, pa_iAddress));
                piNumberOfRecords++;
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Zisti, ci sa v bloku nachadza zaznam s danym klucom
        /// </summary>
        /// <param name="pa_aKey"></param>
        /// <param name="pa_iCount"></param>
        /// <returns></returns>
        public int containsKey(byte[] pa_aKey, int pa_iCount)
        {
            int iFound = 0;
            for (int ii = 0; ii < piNumberOfRecords; ii++)
            {
                if (paValues[ii].equalsKey(pa_aKey) == true)
                {
                    iFound++;
                }
                if (iFound == pa_iCount)
                {
                    return ii;
                }
            }
            return -1;
        }

        /// <summary>
        /// Zisti, ci sa v bloku nachadza zaznam s danym klucom a rowid
        /// </summary>
        /// <param name="pa_aKey"></param>
        /// <param name="pa_iRowid"></param>
        /// <returns></returns>
        public int containsKey(byte[] pa_aKey, long pa_iRowid)
        {
            for (int ii = 0; ii < piNumberOfRecords; ii++)
            {
                if (paValues[ii].equalsKey(pa_aKey) == true && paValues[ii].iRowid == pa_iRowid)
                {
                    return ii;
                }
            }
            return -1;
        }

        public void deleteRecord(int pa_iPosition)
        {
            paValues.RemoveAt(pa_iPosition);
        }
    }
}
